- 前后端分离的场景下,为了满足不同业务需求,Controller 层接口可能会返回类似下面的数据。实际开发中,不同开发人员如果有不同的数据封装方式,后端数据传递到前端数据就会不统一,导致数据传递的多样化。前端获取数据时,分析数据时就会混乱,同时也会导致无法分辨 null 值和数据为空的情况。
- 为了解决这个问题,就需要对数据的封装方式进行统一,目前标准的数据封装方式必须包含三种数据,除此之外 的其他数据可以根据业务进行增加(例如接口调用的时间戳等)
数据 |
说明 |
code |
请求码,说明数据是何种操作及是否操作成功 |
data |
结果数据,包含所有返回的数据 |
message(msg) |
提示信息,说明接口返回的错误信息 |
- 后端可以将数据作为参数统一封装在一个实体类模型中,请求码封装在枚举类中,每个错误码对应消息。模型类和枚举类的的名称可以自定义,这里以 Result 和 Code 为例:
示例
- Code.java
public enum Code { /** 操作成功 */ SUCCESS(200,"成功"),
/** 客户端请求错误 */ BAD_REQUEST(400,"客户端请求错误"),
/** 未授权访问 */ UNAUTHORIZED(401,"未授权访问"),
/** 没有权限 */ FORBIDDEN(403,"没有权限"),
/** 资源不存在 */ NOT_FOUND(404,"资源不存在"),
/** 请求方法不支持 */ METHOD_NOT_ALLOWED(405,"请求方法不支持"),
/** 请求超时 */ REQUEST_TIMEOUT(408,"请求超时"),
/** 服务器内部错误 */ INTERNAL_SERVER_ERROR(500,"服务器内部错误"),
/** 服务不可用 */ SERVICE_UNAVAILABLE(503,"服务不可用"),
/** 网关超时 */ GATEWAY_TIMEOUT(504,"网关超时");
private final int code; private final String msg;
Code(int code, String msg) { this.code = code; this.msg = msg; }
public int getCode() { return code; }
public String getMsg() { return msg; } }
|
- Result.java
public class Result<T> { private int code; private T data; private String msg;
public Result() { }
public Result(T data) { this.code = ResultCode.SUCCESS.getCode(); this.data = data; this.msg = ResultCode.SUCCESS.getMsg(); }
public Result(ResultCode resultCode, T data) { this.code = resultCode.getCode(); this.data = data; this.msg = resultCode.getMsg(); }
public Result(ResultCode resultCode, String msg, T data) { this.code = resultCode.getCode(); this.data = data; this.msg = msg; }
public static <T> Result<T> success(T data) { return new Result<>(ResultCode.SUCCESS, data); }
public static <T> Result<T> fail(ResultCode resultCode, String msg, T data) { return new Result<>(resultCode, msg, data); }
public int getCode() { return code; }
public void setCode(int code) { this.code = code; }
public T getData() { return data; }
public void setData(T data) { this.data = data; }
public String getMsg() { return msg; }
public void setMsg(String msg) { this.msg = msg; } }
|
- BookController.java
@RestController @RequestMapping("/books") public class BookController {
@Resource private BookService bookService;
@PostMapping public Result<Boolean> save(@RequestBody Book book) { boolean flag = bookService.save(book); if (!flag) { return Result.fail(ResultCode.INTERNAL_SERVER_ERROR, ResultCode.INTERNAL_SERVER_ERROR.getMsg(), flag); } return Result.success(flag); }
@PutMapping public Result<Boolean> update(@RequestBody Book book) { boolean flag = bookService.update(book); if (flag) { return Result.fail(ResultCode.INTERNAL_SERVER_ERROR, ResultCode.INTERNAL_SERVER_ERROR.getMsg(), flag); } return Result.success(flag); }
@DeleteMapping("/{id}") public Result<Boolean> delete(@PathVariable Integer id) { boolean flag = bookService.delete(id); if (!flag) { return Result.fail(ResultCode.NOT_FOUND, ResultCode.NOT_FOUND.getMsg(), flag); } return Result.success(flag);
}
@GetMapping("/{id}") public Result<Book> getById(@PathVariable Integer id) { Book book = bookService.getById(id); if (book == null) { return Result.fail(ResultCode.NOT_FOUND, ResultCode.NOT_FOUND.getMsg(), book); } return Result.success(book); }
@GetMapping public Result<List> getAll() { List<Book> bookList = bookService.getAll(); if (bookList == null) { return Result.fail(ResultCode.NOT_FOUND, "数据查询失败,请重试!", bookList); } return Result.success(bookList); } }
|
接口数据返回如下: